package coroutine

import (
	"fmt"
	"sync"
	"time"
)

// AsyncCoroutine 阻塞协程
func AsyncCoroutine() {
	startTime := time.Now()
	var wg sync.WaitGroup
	// 主线程开始运行
	fmt.Println("The main thread starts running......")
	wg.Add(2)
	go func(name string) {
		defer wg.Done()
		time.Sleep(2 * time.Second)
		fmt.Printf("我是异步1:%s\n", name)
	}("小明")
	go func(name string) {
		defer wg.Done()
		time.Sleep(2 * time.Second)
		fmt.Printf("我是异步1:%s\n", name)
	}("小张")
	wg.Wait()
	fmt.Println("The main thread ends running......")
	fmt.Println("program perform times:", time.Since(startTime))
}

// GrabTickets 模拟2000人抢500票
func GrabTickets() {
	// 票数
	ticker := 500
	// 定义一个计数协程的内部有一个计数器，用于跟踪goroutine的数量。
	var wg sync.WaitGroup
	var mu sync.Mutex
	// 模拟2000人抢500张票的情况
	for i := 0; i < 2000; i++ {
		wg.Add(1)
		go func(userId int) {
			// 计数器-1 defer用于函数返回前最后执行,应用场景资源释放
			defer wg.Done()
			// 对操作的数据上锁
			mu.Lock()
			// 在操作完成后释放锁
			defer mu.Unlock()
			if ticker > 0 {
				ticker--
				fmt.Printf("用户: %d ,购票成功!,剩余票数: %d\n", userId, ticker)
			} else {
				fmt.Printf("用户: %d ,购票失败!,剩余票数:%d \n", userId, ticker)
			}
		}(i)
	}
	// 等待协程执行完毕
	wg.Wait()
}
